Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allowing to define variable line heights #233110

Open
wants to merge 52 commits into
base: main
Choose a base branch
from
Open

Allowing to define variable line heights #233110

wants to merge 52 commits into from

Conversation

aiday-mar
Copy link
Contributor

@aiday-mar aiday-mar commented Nov 5, 2024

fixes #147067

Decorations may affect line wrapping. For example, they make make the
text bold, or increase or decrease font size. This wasn’t originally
taken into account to calculate the the break offsets.
@aiday-mar aiday-mar self-assigned this Nov 5, 2024
@aiday-mar aiday-mar changed the title Exploration: implementing variable line heights Allowing to define variable line heights Jan 8, 2025
@aiday-mar aiday-mar requested a review from alexdima January 8, 2025 14:13
@aiday-mar aiday-mar marked this pull request as ready for review January 8, 2025 14:13
@aiday-mar aiday-mar enabled auto-merge (squash) January 8, 2025 14:13
@vs-code-engineering vs-code-engineering bot added this to the January 2025 milestone Jan 8, 2025
@aiday-mar aiday-mar removed request for jrieken and mjbvz January 8, 2025 15:05
src/vs/editor/common/model.ts Outdated Show resolved Hide resolved
@@ -97,6 +97,7 @@ export class LinesLayout {
private _lineHeight: number;
private _paddingTop: number;
private _paddingBottom: number;
private _specialLineHeights = new Map<number, number>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's implement this using a more performant data structure which makes things slow only when the feature is exercised. For example, for a file with 100K lines, getting the top position for line 99K will involve querying this _specialLineHeights map 99K times.

It also seems to me that we're not quite keeping this field up to date correctly. If I set a line height of 40 on a line 1000 and then press enter on the first line, will the _specialLineHeights be updated correctly to reflect the edit I did?

Copy link
Contributor Author

@aiday-mar aiday-mar Jan 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the comment. The way that the line height is currently calculated is:

private _linesHeight(_untilLineNumber?: number): number {
   const untilLineNumber = _untilLineNumber ?? this._lineCount;
   let specialLinesHeight = 0;
   let numberOfSpecialLines = 0;
   this._specialLineHeights.forEach((height, lineNumber) => {
      if (lineNumber <= untilLineNumber) {
         specialLinesHeight += height;
         numberOfSpecialLines++;
      }
   });
   const nonSpecialLinesHeight = (untilLineNumber - numberOfSpecialLines) * this._lineHeight;
   return specialLinesHeight + nonSpecialLinesHeight;
}

Supposing we want to query the height of line 99K and between line 1 and line 99K there are for example 5 special line heights, then we will query the map only 5 times in the code above, as we iterate over the special line heights and add the line heights of the lines below our line of interest. Please let me know if I am misunderstanding what you mean, so I can rework the code.

Concerning the second point, the map is updated when the onDidChangeSpecialLineHeight event is fired. This event is fired when we detect that the line height decoration changes. The decorations change event is also fired when edits are applied in the editor. From this I believe the special line heights should be synchronized.

src/vs/editor/common/viewLayout/viewLinesViewportData.ts Outdated Show resolved Hide resolved
src/vs/editor/browser/view/viewLayer.ts Outdated Show resolved Hide resolved
src/vs/editor/common/viewModel.ts Outdated Show resolved Hide resolved
src/vs/editor/common/textModelEvents.ts Outdated Show resolved Hide resolved
src/vs/editor/common/textModelEvents.ts Outdated Show resolved Hide resolved
Comment on lines +1776 to +1780
private _getLineHeightForLine(lineNumber: number): number | null {
const startOffset = this._buffer.getOffsetAt(lineNumber, 1);
const endOffset = startOffset + this._buffer.getLineLength(lineNumber);
return this._decorationsTree.getLineHeightInInterval(this, startOffset, endOffset, 0);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is something not quite correct here. Line heights don't work quite like injected text, because we should allow for line heights of the same line to be different across different editors. For example, if a particular text model is shown in editor1 and editor2, we should allow that a particular line has a particular height in editor1 and a different height in editor2, since line height is a presentation option (which is arguably different than injected text). So I think the decoration ownerId should play a part in this method call, not quite sure who calls it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support variable line heights in the editor
4 participants